/*
 * Copyright (c) 2011 Imre Fazekas.
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the name of the Brillien nor the names of its
 * terms and concepts may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.vii.brillien.services;

import com.vii.brillien.core.component.websocket.BrillienWebSocketApplication;
import com.vii.brillien.core.management.BrillienServices;
import com.vii.brillien.ignition.BrillienContext;
import com.vii.brillien.kernel.BrillienException;
import com.vii.brillien.services.components.time.Timer;
import com.vii.brillien.services.components.util.MessageQueue;
import com.vii.brillien.services.jsonrpc.BrillienJsonRpcServlet;
import com.vii.brillien.services.websocket.applications.HelloWebSocketApplication;
import com.vii.streamline.services.reflection.ReflectionServices;
import com.vii.streamline.webserver.WebServer;
import com.vii.streamline.webserver.WelcomeServlet;

import javax.servlet.http.HttpServlet;
import java.util.Map;
import java.util.logging.Level;

/**
 * Loader class to publish presences defined in services modul of Brillien
 */
public class ServiceLoader {

    public static void startServices() throws BrillienException {

        BrillienServices.liaison.registerPresence(Timer.class);
        BrillienServices.liaison.registerPresence(MessageQueue.class);

        if (BrillienContext.WEBSERVER_ON) {
            WebServer.addHttpService(
                    "/welcome", "/Hello", new WelcomeServlet()
            );

            BrillienContext.systemLog(Level.CONFIG, "Adding " + BrillienJsonRpcServlet.class.getName() + " servlet to the Web server...");

            for( Map<String, String> servlet : BrillienContext.WEBSERVER_SERVLETS ){
                try{
                    Class cType = ServiceLoader.class.getClassLoader().loadClass( servlet.get("providerClass") );
                    HttpServlet servletInstance = null;
                    try{
                        servletInstance = ReflectionServices.invokeMethod( "getServletInstance", cType );
                    } catch (Exception e){ servletInstance = (HttpServlet)cType.newInstance(); }
                    WebServer.addHttpService(
                            servlet.get("context").toString(),
                            servlet.get("path").toString(),
                            servletInstance,
                            null//new InnerMap<String, String>( "enabledForExtensions", "true" )
                    );
                } catch (Exception e){ e.printStackTrace(); }
            }

            if( BrillienContext.WEBSERVER_WEBSOCKET_ON ){
                WebServer.activateWebsockets();

                String hurl = BrillienContext.WEBSERVER_WEBSOCKET_CONTEXT + "/Hello";
                HelloWebSocketApplication.getWebSocketApplicationInstance().setServiceContext( hurl );
                WebServer.addWebSocketApplication( hurl, HelloWebSocketApplication.getWebSocketApplicationInstance() );

                for( Map<String, String> websocketapplication : BrillienContext.WEBSERVER_WEBSOCKET_APPLICATINS ){
                    try{
                        String wurl = BrillienContext.WEBSERVER_WEBSOCKET_CONTEXT + websocketapplication.get("path");
                        Class c = ServiceLoader.class.getClassLoader().loadClass( websocketapplication.get("providerClass") );
                        BrillienWebSocketApplication wsa = ReflectionServices.<BrillienWebSocketApplication>invokeMethod( "getWebSocketApplicationInstance", c );
                        wsa.initWebSocketApplication();
                        wsa.setServiceContext( wurl );
                        WebServer.addWebSocketApplication( wurl, wsa );
                    } catch (Exception e){
                        throw new BrillienException( e );
                    }
                }
            }

            BrillienContext.systemLog(Level.CONFIG, BrillienJsonRpcServlet.class.getName() + " servlet added to the Web server...");
        }
    }

}
